package pruebas;

import junit.framework.TestCase;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import juego.AvionCivil;
import juego.Botin;
import juego.Cohete;
import juego.Coordenada;
import juego.Energia;
import juego.Helicoptero;
import juego.Impacto;
import juego.Laser;
import juego.Movil;
import juego.Proyectil;
import juego.Torpedo;
import juego.TorpedoRastreador;
import juego.Tripulado;


public class TestTorpedoRastreador extends TestCase {

	
	public void testAusenciaEnemigos(){
		ArrayList<Movil> listaDeObjetos = new ArrayList<Movil>();
		ArrayList<Botin> listaDeBotines = new ArrayList<Botin>();
		
		Coordenada coordT1 = new Coordenada(0,40);
		TorpedoRastreador t1 = new TorpedoRastreador(coordT1);
		listaDeObjetos.add(t1);
		
		int puntaje = (t1.vivir(listaDeObjetos,listaDeBotines));
		assertTrue(puntaje == 0);
		
		Coordenada coord1 = t1.verUbicacion();
		int x1 = coord1.obtenerCoordenadaX();
		int y1 = coord1.obtenerCoordenadaY();
		assertTrue(x1 == (0));
		assertTrue(y1 == (50));
		
		Coordenada coordL1 = new Coordenada(10,30);
		Laser l1 = new Laser(coordL1);
		
		Helicoptero h1 = new Helicoptero(-10,30);
		
		AvionCivil a1 = new AvionCivil(0,40);
		
		listaDeObjetos.add(l1);
		listaDeObjetos.add(h1);
		listaDeObjetos.add(a1);
		
		puntaje = (t1.vivir(listaDeObjetos,listaDeBotines));
		assertTrue(puntaje == 0);
		
		Coordenada coord2 = t1.verUbicacion();
		int x2 = coord2.obtenerCoordenadaX();
		int y2 = coord2.obtenerCoordenadaY();
		assertTrue(x2 == (0));
		assertTrue(y2 == (60));	
		
	}
	
	public void testAusenciaEnemigos2(){
		ArrayList<Movil> listaDeObjetos = new ArrayList<Movil>();
		ArrayList<Botin> listaDeBotines = new ArrayList<Botin>();
		
		Coordenada coordT1 = new Coordenada(0,20);
		TorpedoRastreador t1 = new TorpedoRastreador(coordT1);
		t1.hacerLeal();
		listaDeObjetos.add(t1);
		
		int puntaje = (t1.vivir(listaDeObjetos,listaDeBotines));
		assertTrue(puntaje == 0);
		
		Coordenada coord1 = t1.verUbicacion();
		int x1 = coord1.obtenerCoordenadaX();
		int y1 = coord1.obtenerCoordenadaY();
		assertTrue(x1 == (0));
		assertTrue(y1 == (10));
		
		Coordenada coordT2 = new Coordenada(10,30);
		TorpedoRastreador t2 = new TorpedoRastreador(coordT2);
		t2.hacerLeal();
		listaDeObjetos.add(t2);
		
		Coordenada coordT3 = new Coordenada(-10,30);
		TorpedoRastreador t3 = new TorpedoRastreador(coordT3);
		t3.hacerLeal();
		listaDeObjetos.add(t3);
		
		listaDeObjetos.add(new Tripulado());
		
		int puntaje2 = (t1.vivir(listaDeObjetos,listaDeBotines));
		assertTrue(puntaje2 == 0);
		
		Coordenada coord2 = t1.verUbicacion();
		int x2 = coord2.obtenerCoordenadaX();
		int y2 = coord2.obtenerCoordenadaY();
		assertTrue(x2 == (0));
		assertTrue(y2 == (0));
		
	}
	
	public void testImpactoProvocado(){
		
		Coordenada lugar = new Coordenada (0,20);
		Proyectil proyectil = new TorpedoRastreador(lugar);
		Energia energia = new Energia(10);
		Impacto impacto = proyectil.impactoProvocado();
		impacto.herir(energia);
		assertEquals(1, energia.verEnergia());
	};
	
	public void testPresenciaEnemigos(){
		
		ArrayList<Movil> listaDeObjetos = new ArrayList<Movil>();
		ArrayList<Botin> listaDeBotines = new ArrayList<Botin>();
		
		Coordenada coordT1 = new Coordenada(0,8);//08
		TorpedoRastreador t1 = new TorpedoRastreador(coordT1);
		t1.hacerLeal();
		listaDeObjetos.add(t1);
		assertEquals(0,t1.verUbicacion().obtenerCoordenadaX());
		assertEquals(8,t1.verUbicacion().obtenerCoordenadaY());
		
		Coordenada coordL1 = new Coordenada(-20,30);
		Laser l1 = new Laser(coordL1);
		l1.hacerLeal();
		listaDeObjetos.add(l1);
	
		Helicoptero h1 = new Helicoptero(4,7);
		listaDeObjetos.add(h1);
		
		AvionCivil a1 = new AvionCivil(0,90);
		listaDeObjetos.add(a1);
		
		int puntaje = (t1.vivir(listaDeObjetos,listaDeBotines));
		assertTrue(puntaje == -200);
		
		assertFalse(listaDeObjetos.contains(t1)); 
		assertFalse(t1.estaVivo());
		assertFalse(listaDeObjetos.contains(h1)); 
		assertFalse(h1.estaVivo());
		
		int puntaje2 = (t1.vivir(listaDeObjetos,listaDeBotines));
		assertTrue(puntaje2 == 0);
		
		assertEquals(2, listaDeObjetos.size());
	
		Coordenada ubicacionT2 = new Coordenada(4,20);
		TorpedoRastreador t2 = new TorpedoRastreador(ubicacionT2);
		t2.hacerLeal();
		listaDeObjetos.add(t2);
		Coordenada coord2 = t2.verUbicacion();
		int x2 = coord2.obtenerCoordenadaX();
		int y2 = coord2.obtenerCoordenadaY();
	
		assertEquals(4,x2);
		assertEquals(20,y2);
		assertEquals(3, listaDeObjetos.size());
		
		AvionCivil a2 = new AvionCivil(0,70);
		listaDeObjetos.add(a2);

		int puntaje3 = t2.vivir(listaDeObjetos, listaDeBotines);
		assertEquals(4,t2.verUbicacion().obtenerCoordenadaX());
		assertEquals(30,t2.verUbicacion().obtenerCoordenadaY());
		assertEquals(4, listaDeObjetos.size());
		assertEquals(0,puntaje3);
		
		puntaje3 = t2.vivir(listaDeObjetos, listaDeBotines);
		assertEquals(4,t2.verUbicacion().obtenerCoordenadaX());
		assertEquals(40,t2.verUbicacion().obtenerCoordenadaY());
		assertEquals(4, listaDeObjetos.size());
		assertEquals(0,puntaje3);
		
		puntaje3 = t2.vivir(listaDeObjetos, listaDeBotines);
		assertEquals(4,t2.verUbicacion().obtenerCoordenadaX());
		assertEquals(50,t2.verUbicacion().obtenerCoordenadaY());
		assertEquals(4, listaDeObjetos.size());
		assertEquals(0,puntaje3);
		
		//aca se mueve en diagonal e impacta
		puntaje3 = t2.vivir(listaDeObjetos, listaDeBotines);
		assertEquals(4,t2.verUbicacion().obtenerCoordenadaX());
		assertEquals(60,t2.verUbicacion().obtenerCoordenadaY());
		puntaje3 = t2.vivir(listaDeObjetos, listaDeBotines);
		assertEquals(2, listaDeObjetos.size());
		assertEquals(-300,puntaje3);
		assertFalse(t2.estaVivo());
		assertFalse(a2.estaVivo());
		
//		
//		assertEquals(-300,puntaje2);
//		assertTrue((listaDeObjetos.size()) == 1);
//		assertFalse(listaDeObjetos.contains(t2));
//		assertTrue(listaDeObjetos.contains(l1)); 
//		assertFalse(listaDeObjetos.contains(a1));
//		assertFalse(a1.estaVivo());
		
		
	}

	public void testPresenciaEnemigos2(){
		
		ArrayList<Movil> listaDeObjetos = new ArrayList<Movil>();
		ArrayList<Botin> listaDeBotines = new ArrayList<Botin>();
		
		Coordenada coordT1 = new Coordenada(0,30);
		TorpedoRastreador t1 = new TorpedoRastreador(coordT1);
		t1.hacerLeal();
		listaDeObjetos.add(t1);
		
		Coordenada coordL1 = new Coordenada(-18,30);
		Laser l1 = new Laser(coordL1);
		l1.hacerLeal();
		listaDeObjetos.add(l1);
	
		Coordenada coordH1 = new Coordenada(0,30);
		Cohete h1 = new Cohete(coordH1);
		h1.hacerLeal();
		listaDeObjetos.add(h1);
		
		Coordenada coordA1 = new Coordenada(3,4);
		Torpedo a1 = new Torpedo(coordA1);
		a1.hacerLeal();
		listaDeObjetos.add(a1);
		
		int puntaje = (t1.vivir(listaDeObjetos,listaDeBotines));
		assertTrue(puntaje == 0);
		
		Coordenada coord1 = t1.verUbicacion();
		int x1 = coord1.obtenerCoordenadaX();
		int y1 = coord1.obtenerCoordenadaY();
		assertTrue(x1 == (0));
		assertTrue(y1 == (20));
		
		assertTrue((listaDeObjetos.size()) == 4);
		
		assertTrue(listaDeObjetos.contains(t1)); 
		assertTrue(listaDeObjetos.contains(h1)); 
		assertTrue(listaDeObjetos.contains(l1));
		assertTrue(listaDeObjetos.contains(a1));

		
	} 

	public void testEstaFueraDelEscenario(){
		
		ArrayList<Movil> listaDeMoviles = new ArrayList<Movil>();
		ArrayList<Botin> listaDeBotines = new ArrayList<Botin>();
		
		Coordenada lugar = new Coordenada (404,460);
		TorpedoRastreador torpedoRastreador = new TorpedoRastreador(lugar);
		listaDeMoviles.add(torpedoRastreador);
		
		assertTrue((listaDeMoviles.size() == 1));
		assertTrue(torpedoRastreador.estaVivo());
		
        torpedoRastreador.vivir(listaDeMoviles,listaDeBotines);
		
		assertTrue((listaDeMoviles.size() == 0));
		assertFalse(torpedoRastreador.estaVivo());
	}
	
	public void testPresenciaEnemigoTripulado(){
		
		ArrayList<Movil> listaDeObjetos = new ArrayList<Movil>();
		ArrayList<Botin> listaDeBotines = new ArrayList<Botin>();
		
		Coordenada coordTorpedoRastreador = new Coordenada(170,200);
		TorpedoRastreador torpedoRastreador = new TorpedoRastreador(coordTorpedoRastreador);
		listaDeObjetos.add(torpedoRastreador);
		Tripulado tripulado = new Tripulado(); //esta en (170,350)
		listaDeObjetos.add(tripulado);
		int puntaje = 0;
		
		//el torpedoRastreador inicialmente se mueve por y
		for (int i=1; i<=14; i++){
			puntaje += (torpedoRastreador.vivir(listaDeObjetos,listaDeBotines));
			assertTrue(puntaje == 0);
			assertEquals(170,torpedoRastreador.verUbicacion().obtenerCoordenadaX());
			int sumaY = 10*i;
			assertEquals(200+sumaY,torpedoRastreador.verUbicacion().obtenerCoordenadaY());
			assertTrue(torpedoRastreador.estaVivo());
		}
		
		//ahora comienza a moverse en forma diagonal
		puntaje += (torpedoRastreador.vivir(listaDeObjetos,listaDeBotines));
		assertTrue(puntaje == 0);
		assertEquals(173,torpedoRastreador.verUbicacion().obtenerCoordenadaX());
		assertEquals(343,torpedoRastreador.verUbicacion().obtenerCoordenadaY());
		
		for(int i =1; i<=4;i++){
			puntaje += (torpedoRastreador.vivir(listaDeObjetos, listaDeBotines));

		}

        assertEquals(0,puntaje);
		assertFalse(torpedoRastreador.estaVivo());
	} 
	
	public void testPresenciaEnemigoTripulado2(){
		
		ArrayList<Movil> listaDeObjetos = new ArrayList<Movil>();
		ArrayList<Botin> listaDeBotines = new ArrayList<Botin>();
		
		Coordenada coordTorpedoRastreador = new Coordenada(120,350);
		TorpedoRastreador torpedoRastreador = new TorpedoRastreador(coordTorpedoRastreador);
		listaDeObjetos.add(torpedoRastreador);
		Tripulado tripulado = new Tripulado(); //esta en (170,350)
		listaDeObjetos.add(tripulado);
		int puntaje = 0;
		for (int i=1; i<=4; i++){
			puntaje += (torpedoRastreador.vivir(listaDeObjetos,listaDeBotines));
			int sumaX = 10*i;
			assertTrue(puntaje == 0);
			assertEquals(120 + sumaX,torpedoRastreador.verUbicacion().obtenerCoordenadaX());
			assertEquals(350,torpedoRastreador.verUbicacion().obtenerCoordenadaY());
			assertTrue(torpedoRastreador.estaVivo());
		}
		puntaje += (torpedoRastreador.vivir(listaDeObjetos,listaDeBotines));
		assertTrue(puntaje == 0);
		assertEquals(163,torpedoRastreador.verUbicacion().obtenerCoordenadaX());
		assertEquals(353,torpedoRastreador.verUbicacion().obtenerCoordenadaY());
		
		for (int i = 1; i<=3; i++){
			torpedoRastreador.vivir(listaDeObjetos,listaDeBotines);
		}

		assertFalse(torpedoRastreador.estaVivo());
	} 
	
	public void testPresenciaEnemigoTripulado3(){
		
		ArrayList<Movil> listaDeObjetos = new ArrayList<Movil>();
		ArrayList<Botin> listaDeBotines = new ArrayList<Botin>();
		
		Coordenada coordTorpedoRastreador = new Coordenada(120,300);
		TorpedoRastreador torpedoRastreador = new TorpedoRastreador(coordTorpedoRastreador);
		listaDeObjetos.add(torpedoRastreador);
		Tripulado tripulado = new Tripulado(); //esta en (170,350)
		listaDeObjetos.add(tripulado);
		int puntaje = 0;
		puntaje += (torpedoRastreador.vivir(listaDeObjetos,listaDeBotines));
		assertTrue(puntaje == 0);
		assertEquals(123 ,torpedoRastreador.verUbicacion().obtenerCoordenadaX());
		assertEquals(303,torpedoRastreador.verUbicacion().obtenerCoordenadaY());
		assertTrue(torpedoRastreador.estaVivo());

	}
	


	private static void persistir(String archivo, Proyectil proyectil) {
		try {

			Document doc = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder().newDocument();

			Element element = proyectil.getElement(doc);
			doc.appendChild(element);

			Transformer transformer = TransformerFactory.newInstance()
					.newTransformer();
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.transform(new DOMSource(doc), new StreamResult(
					new PrintStream(archivo)));

		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerFactoryConfigurationError e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}
	}

	private static TorpedoRastreador recuperar(String archivo) {
		try {
		
			Document doc = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder().parse(new File(archivo));
			Element element = doc.getDocumentElement();

			TorpedoRastreador proyectil = TorpedoRastreador.fromElement(element);
			return proyectil;
		
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
	
		return null;
	}



	public void testPersistencia() {

		String archivo = "torpedoRastreador_java.xml";
		TorpedoRastreador proyectilOriginal = new TorpedoRastreador(new Coordenada(5,40));
		assertTrue(proyectilOriginal.estaVivo());
		proyectilOriginal.hacerLeal();
		persistir(archivo, proyectilOriginal);
		TorpedoRastreador proyectilRecuperado = recuperar(archivo);
		assertEquals(5,proyectilRecuperado.getX());
		assertEquals(40,proyectilRecuperado.getY());
		assertTrue(proyectilRecuperado.verLealtad());
		assertTrue(proyectilRecuperado.estaVivo());
	
//		System.out.println(proyectilRecuperado.getClass());
	}
	


}
